<template>
  <el-drawer :model-value="visible" size="720px" :with-header="true" @close="onClose">
    <template #header>
      <div class="drawer-header">
        <span class="node-icon" v-if="nodeIconUnicode" :style="{ color: nodeIconColor }">{{ nodeIconUnicode }}</span>
        <span class="title">代码工具</span>
      </div>
    </template>

    <div class="drawer-body">
      <el-form :model="form" label-position="left" class="name-form">
        <el-form-item label="名称">
          <el-input v-model="form.name" maxlength="10" placeholder="请输入名称（最多10字）" />
        </el-form-item>
      </el-form>

      <div class="section">
        <div class="section-header">
          <span>输入变量</span>
          <el-button type="primary" link @click="addInput">新增变量</el-button>
        </div>
        <div class="kv-list">
          <div class="kv-row kv-row--vars" v-for="(v, i) in form.inputs" :key="i">
            <el-input v-model="v.name" placeholder="变量名" @input="emitSave" />
            <el-input v-model="v.mapping" placeholder="Set variable" @input="emitSave" />
            <el-button circle size="small" type="danger" class="del-btn" @click="removeInput(i)"><el-icon><Close /></el-icon></el-button>
          </div>
        </div>
      </div>

      <div class="section">
        <div class="section-header">
          <span>语言</span>
          <el-radio-group v-model="form.language" @change="onLanguageChange" class="lang-radio">
            <el-radio-button label="python">Python3</el-radio-button>
            <el-radio-button label="javascript">JavaScript</el-radio-button>
          </el-radio-group>
        </div>
        <div class="code-editor">
          <div class="editor-toolbar">
            <el-button size="small" @click="formatCode">格式化</el-button>
          </div>
          <VueMonacoEditor
            v-model:value="form.source"
            :language="form.language === 'javascript' ? 'javascript' : 'python'"
            theme="vs-dark"
            :options="editorOptions"
            class="monaco-container"
            :style="{ height: '400px' }"
          />
        </div>
      </div>

      <div class="section">
        <div class="section-header">
          <span>输出变量</span>
          <el-button type="primary" link @click="addOutput">新增变量</el-button>
        </div>
        <div class="kv-list">
          <div class="kv-row kv-row--outputs" v-for="(o, i) in form.outputs" :key="i">
            <el-input v-model="o.name" placeholder="变量名" @input="emitSave" />
            <el-select v-model="o.type" placeholder="类型" class="type-select" @change="emitSave">
              <el-option v-for="t in typeOptions" :key="t" :label="t" :value="t" />
            </el-select>
            <el-button circle size="small" type="danger" class="del-btn" @click="removeOutput(i)"><el-icon><Close /></el-icon></el-button>
          </div>
        </div>
      </div>
    </div>
  </el-drawer>
</template>

<script>
import { defineComponent, reactive, watch, computed, ref } from 'vue'
import { Close } from '@element-plus/icons-vue'
import { componentRegistry } from '@/components/WorkFlow/core/ComponentRegistry'
import { VueMonacoEditor, loader } from '@guolao/vue-monaco-editor'
import { js as jsBeautify } from 'js-beautify'

export default defineComponent({
  name: 'CodeDrawer',
  components: { Close },
  props: {
    visible: { type: Boolean, default: false },
    nodeData: { type: Object, default: null }
  },
  emits: ['save', 'close'],
  setup(props, { emit }) {
    const typeOptions = ['String', 'Number', 'Boolean', 'Array', 'Object']
    const form = reactive({ name: '', language: 'python', source: '', inputs: [], outputs: [] })
    const isAutoSource = ref(true)
    const editorOptions = {
      automaticLayout: true,
      minimap: { enabled: false },
      fontSize: 13,
      scrollBeyondLastLine: false,
      smoothScrolling: true
    }
    loader.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.54.0/min/vs' } })

    /**
     * 初始化表单数据
     * @returns {void}
     */
    const initForm = () => {
      const d = props.nodeData || {}
      const code = d.code || {}
      form.name = (d.name || '').toString().slice(0, 10)
      form.language = code.language || 'python'
      if (code.source && code.source.trim() !== '') {
        form.source = code.source
        isAutoSource.value = false
      } else {
        form.source = getDefaultSource(form.language)
        isAutoSource.value = true
      }
      form.inputs = Array.isArray(code.inputs) ? code.inputs.map(x => ({ ...x })) : []
      form.outputs = Array.isArray(code.outputs) ? code.outputs.map(x => ({ ...x })) : []
    }

    /**
     * 构建默认代码模板（随语言和变量自动调整）
     * @param {string} lang 语言
     * @returns {string}
     */
    const buildSourceFromModel = (lang) => {
      if (lang === 'javascript') {
        return `function main(arg1,arg2){\n  return arg1+arg2;\n}`
      }
      return `def main(arg1: int, arg2: int) -> dict:\n    return {\n        \"result\": (arg1 or 0) + (arg2 or 0)\n    }`
    }

    const getDefaultSource = (lang) => buildSourceFromModel(lang)

    /**
     * 语言切换时更新默认模板
     * @returns {void}
     */
    const onLanguageChange = () => {
      if (isAutoSource.value || !form.source || form.source.trim() === '') {
        form.source = buildSourceFromModel(form.language)
        isAutoSource.value = true
      }
      emitSave()
    }

    /**
     * 代码编辑器内容变更
     * @param {string} val 新内容
     * @returns {void}
     */
    const onCodeChange = (val) => {
      form.source = val || ''
      isAutoSource.value = false
      emitSave()
    }

    /**
     * 代码格式化
     * @returns {void}
     */
    const formatCode = () => {
      if (form.language === 'javascript') {
        form.source = jsBeautify(form.source || '', { indent_size: 2, space_in_empty_paren: true })
      }
      emitSave()
    }

    /**
     * 上抛实时保存
     * @returns {void}
     */
    const emitSave = () => {
      emit('save', {
        code: {
          language: form.language,
          source: form.source,
          inputs: form.inputs,
          outputs: form.outputs
        }
      })
    }

    /**
     * 新增输入变量
     * @returns {void}
     */
    const addInput = () => { form.inputs.push({ name: '', mapping: '' }); emitSave() }

    /**
     * 删除输入变量
     * @param {number} i 索引
     * @returns {void}
     */
    const removeInput = (i) => { form.inputs.splice(i, 1); emitSave() }

    /**
     * 新增输出变量
     * @returns {void}
     */
    const addOutput = () => { form.outputs.push({ name: '', type: 'String' }); emitSave() }

    /**
     * 删除输出变量
     * @param {number} i 索引
     * @returns {void}
     */
    const removeOutput = (i) => { form.outputs.splice(i, 1); emitSave() }

    /**
     * 关闭抽屉时保存名称
     * @returns {void}
     */
    const onClose = () => {
      const name = (form.name || '').toString().slice(0, 10)
      if (name) emit('save', { name })
      emit('close')
    }

    /**
     * 获取节点图标及颜色
     * @returns {string}
     */
    const nodeIconUnicode = computed(() => componentRegistry.getNodeConfig('code')?.iconUnicode || '')
    const nodeIconColor = computed(() => {
      const cfg = componentRegistry.getNodeConfig('code')
      return props.nodeData?.color || cfg?.color || '#333333'
    })

    watch(() => props.nodeData, () => initForm(), { immediate: true })
    watch(() => form, () => emitSave(), { deep: true })
    watch(() => [form.inputs, form.outputs], () => {
      if (isAutoSource.value) {
        form.source = buildSourceFromModel(form.language)
        emitSave()
      }
    }, { deep: true })

    return {
      form,
      typeOptions,
      editorOptions,
      isAutoSource,
      addInput,
      removeInput,
      addOutput,
      removeOutput,
      emitSave,
      onLanguageChange,
      onCodeChange,
      formatCode,
      onClose,
      nodeIconUnicode,
      nodeIconColor
    }
  }
})
</script>

<style scoped>
.drawer-header { display: flex; align-items: center; gap: 8px; }
.node-icon { font-family: iconfont; font-size: 20px; line-height: 1; }
.title { font-size: 16px; font-weight: 600; }
.drawer-body { padding: 8px 4px 16px 4px; }
.name-form :deep(.el-form-item__label) { width: auto !important; text-align: left; padding-right: 8px; }
.section { margin-top: 12px; }
.section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.kv-list { display: flex; flex-direction: column; gap: 8px; }
.kv-row { display: grid; gap: 8px; align-items: center; }
.kv-row--vars { grid-template-columns: 1fr 1fr 44px; }
.kv-row--outputs { grid-template-columns: 1fr 160px 44px; }
.type-select { width: 160px; }
.del-btn { padding: 2px; height: 24px; }
.del-btn :deep(.el-icon) { font-size: 14px; }
.mono :deep(textarea.el-textarea__inner) { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
.code-editor { margin-top: 4px; }
.monaco-container { height: 360px; border: 1px solid #ebeef5; border-radius: 4px; }
.editor-toolbar { display: flex; justify-content: flex-end; margin-bottom: 6px; }
.lang-radio :deep(.el-radio-button__inner) { padding: 6px 10px; }
</style>
